package com.karson.admin.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import com.karson.common.model.StorageConfig;
import com.karson.common.model.UploadFile;
import com.karson.common.request.CreateMultipartUpload;
import com.karson.common.request.MergeRequest;
import com.karson.common.response.CommonResult;
import com.karson.common.util.FileTypeUtil;
import com.karson.common.vo.FileAlbumResultVo;
import com.karson.common.vo.FileResultVo;
import com.karson.service.service.IStorageService;
import com.karson.service.service.StorageServiceFactory;
import com.karson.service.service.UploadService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("api/upload")
@Tag(name = "上传接口")
public class UploadController {

    @Autowired
    private UploadService uploadService;

    @Operation(description = "文件上传")
    @PostMapping("/file")
    public CommonResult<FileAlbumResultVo> file(@Parameter(description = "上传的文件", required = true, content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE))
                                               @RequestPart("multipart")MultipartFile multipart,
                                                @RequestParam(value = "model") String model,
                                                @RequestParam(value = "pid") Integer pid) throws IOException {
        return CommonResult.success(uploadService.fileUpload(multipart, model, pid));
    }

    @Operation(
            summary = "图片上传",
            description = "上传图片到指定模块和分类"
    )
    @PostMapping(value = "/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public CommonResult<FileResultVo> image(
            @Parameter(description = "上传的图片文件")
            @RequestPart("multipart") MultipartFile multipart) throws IOException {
        return CommonResult.success(uploadService.imageUpload(multipart));
    }

    @Resource
    private StorageServiceFactory storageServiceFactory;

    /**
     * 从请求中获取存储类型（示例：从请求头获取）
     * @param request HTTP 请求对象
     * @return 存储类型（"MINIO" 或 "LOCAL"）
     */
    private String getStorageTypeFromRequest(HttpServletRequest request) {
        String storageType = request.getHeader("Storage-Type");
        if (storageType == null || storageType.trim().isEmpty()) {
            storageType = StorageConfig.LOCAL; // 默认值
        }
        return storageType;
    }

    @GetMapping("/getUploadProgress")
    public CommonResult<?> getUploadProgress(HttpServletRequest request, String identifier) {
        String storageType = getStorageTypeFromRequest(request);
        IStorageService storageService = storageServiceFactory.getStorageService(storageType);
        return CommonResult.success(storageService.getUploadProgress(identifier));
    }

    @PostMapping("/createMultipartUpload")
    public CommonResult<?> createMultipartUpload(HttpServletRequest request, @Valid @RequestBody CreateMultipartUpload req) {
        String storageType = getStorageTypeFromRequest(request);
        IStorageService storageService = storageServiceFactory.getStorageService(storageType);
        return CommonResult.success(storageService.createMultipartUpload(req));
    }

    @GetMapping("/getPreSignUploadUrl")
    public CommonResult<?> getPreSignUploadUrl(HttpServletRequest request, String identifier, Integer partNumber) {
        String storageType = getStorageTypeFromRequest(request);
        IStorageService storageService = storageServiceFactory.getStorageService(storageType);
        UploadFile uploadFile = storageService.getByIdentifier(identifier);
        if (uploadFile == null) {
            return CommonResult.success("分片任务不存在");
        }
        Map<String, String> params = new HashMap<>();
        params.put("partNumber", partNumber.toString());
        params.put("uploadId", uploadFile.getUploadId());
        Map<String, String> data = new HashMap<>();
        String url = storageService.genPreSignUploadUrl(uploadFile.getObjectKey(), params);
        data.put("url", url);
        return CommonResult.success(data);
    }

    @PostMapping("/part")
    public CommonResult<?> uploadPart(
            HttpServletRequest request,
            @RequestParam("uploadId") String uploadId,
            @RequestParam("partNumber") Integer partNumber,
            @RequestParam("file") MultipartFile partFile) {
        String storageType = getStorageTypeFromRequest(request);
        IStorageService storageService = storageServiceFactory.getStorageService(storageType);
        storageService.uploadPart(uploadId, partNumber, partFile);
        return CommonResult.success("分片上传成功");
    }

    @PostMapping("/merge")
    public CommonResult<?> merge(HttpServletRequest request, @RequestBody MergeRequest merge) {
        String storageType = getStorageTypeFromRequest(request);
        IStorageService storageService = storageServiceFactory.getStorageService(storageType);
        return CommonResult.success(storageService.merge(merge.getIdentifier(), true));
    }

    @PostMapping
    public CommonResult<?> uploadFile(HttpServletRequest request, @RequestPart("file")MultipartFile file, String folder, Integer fileType) throws IOException {
        if (file == null || file.getBytes().length == 0) {
            return CommonResult.failed("上传文件不能为空");
        }
        String filename = file.getOriginalFilename();
        if (fileType != null) {
            String fileTypeExists = FileTypeUtil.isFileTypeExists(fileType, filename);
            if (fileTypeExists != null) {
                return CommonResult.success("数据格式不正确");
            }
        }
        //判断是否登录
        boolean login = StpUtil.isLogin();

        String md5 = SecureUtil.md5(file.getInputStream());
        synchronized (md5.intern()) {
            String dateFormat = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
            assert filename != null;
            String objectName = (folder == null ? "default" : folder) + "/" +
                    dateFormat + "/" + md5 + "." + FileTypeUtil.getFileSuffix(filename);
            String storageType = getStorageTypeFromRequest(request);
            IStorageService storageService = storageServiceFactory.getStorageService(storageType);
            return CommonResult.success(storageService.uploadFile(file, md5, objectName,login));
        }
    }
}
